package com.member.api.SMUtils;

import org.apache.tomcat.util.codec.binary.Base64;

import java.net.URLDecoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

public class SM4MainUtil {
	
	private static final String IV = "abcd0863ef9087ced675985321bedf67";//固定这个值

	// 加密算法
	public static String encryptNationalSerAlgorithmCBC(String cipherText, String key) throws Exception {
		try {
			SM4_Context ctx = new SM4_Context();
			ctx.isPadding = true;
			ctx.mode = SM4.SM4_ENCRYPT;

			byte[] keyBytes;
			byte[] ivBytes;
			keyBytes = hexStringToBytes(key);
			ivBytes = hexStringToBytes(IV);

			SM4 sm4 = new SM4();
			sm4.sm4_setkey_enc(ctx, keyBytes);
			byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, cipherText.getBytes("UTF-8"));
			return byteToHex(encrypted);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	// 解密算法
	public static String decryptNationalSerAlgorithmCBC(String cipherText, String secretKey) throws Exception {
		try {
			byte[] encrypted = hexToByte(cipherText);
			cipherText = Base64.encodeBase64String(encrypted);
			if (cipherText != null && cipherText.trim().length() > 0) {
				Pattern p = compile("\\s*|\t|\r|\n");
				Matcher m = p.matcher(cipherText);
				cipherText = m.replaceAll("");
			}
			SM4_Context ctx = new SM4_Context();
			ctx.isPadding = true;
			ctx.mode = SM4.SM4_DECRYPT;

			byte[] keyBytes;
			byte[] ivBytes;

			keyBytes = hexStringToBytes(secretKey);
			ivBytes = hexStringToBytes(IV);

			SM4 sm4 = new SM4();
			sm4.sm4_setkey_dec(ctx, keyBytes);
			byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Base64.decodeBase64(cipherText));
			return new String(decrypted, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}

		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	public static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	/**
	 * 十六进制串转化为byte数组
	 *
	 * @return the array of byte
	 */
	public static byte[] hexToByte(String hex) throws IllegalArgumentException {
		if (hex.length() % 2 != 0) {
			throw new IllegalArgumentException();
		}
		char[] arr = hex.toCharArray();
		byte[] b = new byte[hex.length() / 2];
		for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
			String swap = "" + arr[i++] + arr[i];
			int byteint = Integer.parseInt(swap, 16) & 0xFF;
			b[j] = new Integer(byteint).byteValue();
		}
		return b;
	}

	/**
	 * 字节数组转换为十六进制字符串
	 *
	 * @param b byte[] 需要转换的字节数组
	 * @return String 十六进制字符串
	 */
	public static String byteToHex(byte b[]) {
		if (b == null) {
			throw new IllegalArgumentException("Argument b ( byte array ) is null! ");
		}
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			stmp = Integer.toHexString(b[n] & 0xff);
			if (stmp.length() == 1) {
				hs = hs + "0" + stmp;
			} else {
				hs = hs + stmp;
			}
		}
		return hs.toLowerCase();
	}

	public static void main(String[] args) {
		try {
			String plainText = "I Love You Every Day";
			String key = "184ca03adfbc11ebabed52540006f7b4";// 分配的秘钥
			String encryplain = SM4MainUtil.encryptNationalSerAlgorithmCBC(plainText, key);
			System.out.println("加密后：" + encryplain);


			encryplain = "120b567b9110e7c9c4a527f21c81ab1cf104b3e91d2767287e932f47b863b7e8";

			String decryplain = SM4MainUtil.decryptNationalSerAlgorithmCBC(encryplain, key);
			System.out.println("解密后：" + URLDecoder.decode(decryplain));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
